home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 112
/
EnigmaAmiga112CD.iso
/
dalla rivista
/
news
/
orbit
/
source
/
sound_amiga.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-05-01
|
6KB
|
257 lines
/*
Load and convert a WAV file, play it with 'ahi.device'
Written by Oliver Gantert
31.04.2000 - Yeah, this works!
*/
#include "orbit.h"
#include <devices/ahi.h>
#include <clib/ahi_protos.h>
#include <stdio.h>
struct RIFF_Header
{
ULONG ChunkID; /* must be 0x52494646 */
ULONG ChunkSize; /* little endian! */
ULONG Format; /* must be 0x57415645 */
ULONG Subchunk1ID; /* must be 0x666d7420 */
ULONG Subchunk1Size; /* little endian, must be 16 */
UWORD AudioFormat; /* little endian, must be 1 */
UWORD NumChannels; /* little endian, Mono = 1, Stereo = 2 */
ULONG SampleRate; /* little endian, 44100 etc. */
ULONG ByteRate; /* little endian, == SampleRate * NumChannels * BitsPerSample/8 */
UWORD BlockAlign; /* little endian, == NumChannels * BitsPerSample/8 */
UWORD BitsPerSample; /* little endian, 8, 16, etc. */
ULONG Subchunk2ID; /* must be 0x64617461 */
ULONG Subchunk2Size; /* little endian, == NumSamples * NumChannels * BitsPerSample/8 */
};
struct ASample
{
ULONG SampleRate;
ULONG Size;
UBYTE *SampleData;
ULONG Type;
};
struct MsgPort *AHImp = NULL;
struct AHIRequest *AHIio = NULL;
struct ASample *smp[3] = {NULL, NULL, NULL};
ULONG ahi_available = 0,
ahi_open = 0;
UWORD ChangeEndianW(UWORD wert)
{
UBYTE t;
union
{
UBYTE c[2];
UWORD w;
} u;
u.w = wert;
t = u.c[0];
u.c[0] = u.c[1];
u.c[1] = t;
return(u.w);
}
ULONG ChangeEndianL(ULONG wert)
{
UBYTE t;
union
{
UBYTE c[4];
ULONG w;
} u;
u.w = wert;
t = u.c[0];
u.c[0] = u.c[3];
u.c[3] = t;
t = u.c[1];
u.c[1] = u.c[2];
u.c[2] = t;
return(u.w);
}
struct ASample *LoadWAVSample(STRPTR filename)
{
struct ASample *smp = NULL;
struct RIFF_Header *riff;
FILE *file;
UWORD *smpdata;
ULONG i;
if (file = fopen(filename, "rb"))
{
if (riff = (struct RIFF_Header *)malloc(sizeof(struct RIFF_Header)))
{
fread(riff, sizeof(struct RIFF_Header), 1, file);
/*
Check if it's a standard RIFF WAVE file.
*/
if ((riff->ChunkID == 0x52494646) && (riff->Format == 0x57415645) &&
(riff->Subchunk1ID == 0x666d7420) && (riff->Subchunk2ID == 0x64617461))
{
riff->Subchunk1Size = ChangeEndianL(riff->Subchunk1Size);
riff->AudioFormat = ChangeEndianW(riff->AudioFormat);
riff->NumChannels = ChangeEndianW(riff->NumChannels);
riff->SampleRate = ChangeEndianL(riff->SampleRate);
riff->BitsPerSample = ChangeEndianW(riff->BitsPerSample);
riff->Subchunk2Size = ChangeEndianL(riff->Subchunk2Size);
/*
More checks.
*/
if ((riff->Subchunk1Size == 16) && (riff->AudioFormat == 1))
{
if (smp = (struct ASample *)malloc(sizeof(struct ASample)))
{
smp->SampleRate = riff->SampleRate;
smp->Size = riff->Subchunk2Size;
if (riff->NumChannels == 1)
{
if (riff->BitsPerSample == 8)
smp->Type = AHIST_M8S;
else
smp->Type = AHIST_M16S;
}
else
{
if (riff->BitsPerSample == 8)
smp->Type = AHIST_S8S;
else
smp->Type = AHIST_S16S;
}
if (smp->SampleData = (UBYTE *)malloc(smp->Size))
{
fread(smp->SampleData, smp->Size, 1, file);
/*
Change endian of 16bit data
*/
if (riff->BitsPerSample > 8)
{
smpdata = (UWORD *)smp->SampleData;
for (i = 0; i < (smp->Size>>1); i++)
{
smpdata[i] = ChangeEndianW(smpdata[i]);
}
}
}
else
{
free(smp);
smp = NULL;
}
}
}
}
free(riff);
}
fclose(file);
}
return(smp);
}
VOID FreeASample(struct ASample *smp)
{
if (smp)
{
if (smp->SampleData)
free(smp->SampleData);
free(smp);
}
}
/*
==============
THE ORBIT PART
==============
*/
int InitSound()
{
if (AHImp = (struct MsgPort *)CreateMsgPort())
{
if (AHIio = (struct AHIRequest *)CreateIORequest(AHImp, sizeof(struct AHIRequest)))
{
AHIio->ahir_Version = 4;
if (!OpenDevice(AHINAME, 0, (struct IORequest *)AHIio, 0))
{
ahi_open = 1;
if (smp[0] = LoadWAVSample("sounds/phaser.wav"))
{
if (smp[1] = LoadWAVSample("sounds/explosion1.wav"))
{
if (smp[2] = LoadWAVSample("sounds/communicator.wav"))
{
AHIio->ahir_Std.io_Message.mn_Node.ln_Pri = 0;
AHIio->ahir_Std.io_Command = CMD_WRITE;
AHIio->ahir_Std.io_Offset = 0;
AHIio->ahir_Volume = 0x10000;
AHIio->ahir_Position = 0x8000;
AHIio->ahir_Link = NULL;
ahi_available = 1;
return(1);
}
FreeASample(smp[1]);
}
FreeASample(smp[0]);
}
CloseDevice((struct IORequest *)AHIio);
}
DeleteIORequest((struct IORequest *)AHIio);
}
DeleteMsgPort(AHImp);
}
return(0);
}
int PlayAudio(enum sounds nSound)
{
if (ahi_available)
{
AHIio->ahir_Std.io_Data = smp[nSound]->SampleData;
AHIio->ahir_Std.io_Length = smp[nSound]->Size;
AHIio->ahir_Frequency = smp[nSound]->SampleRate;
AHIio->ahir_Type = smp[nSound]->Type;
SendIO((struct IORequest *)AHIio);
return(1);
}
return(0);
}
void FinishSound()
{
if (ahi_available)
{
WaitIO((struct IORequest *)AHIio);
ahi_available = 0;
}
if (AHIio)
{
if (ahi_open)
{
CloseDevice((struct IORequest *)AHIio);
ahi_open = 0;
}
DeleteIORequest((struct IORequest *)AHIio);
AHIio = NULL;
}
if (AHImp)
{
DeleteMsgPort(AHImp);
AHImp = NULL;
}
if (smp[0])
FreeASample(smp[0]);
if (smp[1])
FreeASample(smp[1]);
if (smp[2])
FreeASample(smp[2]);
}